package com.lagou.filter;

import com.lagou.bean.MethodInfo;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Activate(group = {CommonConstants.CONSUMER})
public class TpMonitorFilter implements Filter,Runnable {

    //key 方法名 value是MethodInfo的list
    Map<String, List<MethodInfo>> map = new ConcurrentHashMap<>();

    public TpMonitorFilter(){
        //每隔5秒打印线程使用情况
        Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(this,5,5, TimeUnit.SECONDS);
        Executors.newSingleThreadScheduledExecutor()
                .scheduleWithFixedDelay(new Thread(new RemoveDataThread(map)), 10,60, TimeUnit.SECONDS);
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Result result = null;
        Long takeTime = 0L;
        try {
            Long startTime = System.currentTimeMillis();
            result = invoker.invoke(invocation);
            if (result.getException() instanceof Exception) {
                throw new Exception(result.getException());
            }

            takeTime = System.currentTimeMillis() - startTime;
        }catch (Exception e){
            e.printStackTrace();
            return result;
        }

        String methodName = invocation.getMethodName();
        List<MethodInfo> methodInfoList = map.get(methodName);
        if(methodInfoList == null){
            methodInfoList = new ArrayList<>();
            map.put(methodName,methodInfoList);
        }
        methodInfoList.add(new MethodInfo(methodName,takeTime,System.currentTimeMillis()));
        return result;
    }

    private long getTP(List<MethodInfo> methodInfoList,double rate){
        List<MethodInfo>  sortInfo = new ArrayList<>();

        //开始时间
        long  endTime = System.currentTimeMillis();

        //结束时间
        long  startTime = endTime - 60000;
        for (int i = 0; i < methodInfoList.size(); i++) {
            MethodInfo methodInfo = methodInfoList.get(i);
            if(methodInfo.getEndTime() >=startTime && methodInfo.getEndTime() <= endTime){
                sortInfo.add(methodInfo);
            }
        }

        sortInfo.sort(new Comparator<MethodInfo>() {
            @Override
            public int compare(MethodInfo o1, MethodInfo o2) {
                if(o1.getCostTime() > o2.getCostTime()){
                    return  1;
                }else if(o1.getCostTime() < o2.getCostTime()){
                    return -1;
                }else{
                    return  0;
                }
            }
        });

        int  index = (int)(sortInfo.size() * rate);

        return sortInfo.get(index).getCostTime();
    }

    @Override
    public void run() {
        Date date = new Date();
        SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String dateStr = sdf.format(date);
        for(Map.Entry<String,List<MethodInfo>> entry : map.entrySet()){
            System.out.println(dateStr + "|" + entry.getKey() +"的TP90是:"+ getTP(entry.getValue(),0.9)+"毫秒," + "TP99是：" + getTP(entry.getValue(),0.99) +"毫秒");
        }
    }
}
